%%%-------------------------------------------------------------------
%%% @author Rain
%%% @copyright (C) 2022, <COMPANY>
%%% @doc
%%%
%%% @end
%%% Created : 16. 5月 2022 10:32
%%%-------------------------------------------------------------------
-module(tower_aoi).
-author("Rain").
-include("tower_aoi.hrl").
-include("obj.hrl").
%% API
-export([piex_pos_2_aoi_pos/4,
    piex_pos_2_aoi_pos/2,
    init_tower_aoi_grid_data/4,
    broadcast/2,
    do_broadcast/2,
    calc_viewport_aoi/1,
    get_object_aoi_type_by_uid/1,
    get_viewport_aoi/1,
    get_tower_data/2,
    set_tower_data/3]).

%% @doc 像素坐标转Aoi坐标
piex_pos_2_aoi_pos(X, Y) ->
    {X div ?DEFAULT_TOWER_X, Y div ?DEFAULT_TOWER_Y}.

piex_pos_2_aoi_pos(TowerX, TowerY, X, Y) ->
    {X div TowerX, Y div TowerY}.

%% @doc 初始化灯塔aoi格子数据
init_tower_aoi_grid_data(MapX, MapY, TowerX, TowerY) ->
    {MaxAoiX, MaxAoiY} = piex_pos_2_aoi_pos(TowerX, TowerY, MapX, MapY),
    PosList = [{AccX, AccY} || AccX <- lists:seq(0, MaxAoiX), AccY <- lists:seq(0, MaxAoiY)],
    init_tower_aoi_grid_data2(PosList).

init_tower_aoi_grid_data2([]) ->
    ok;
init_tower_aoi_grid_data2([AoiPos | T]) ->
    ViewportAoi = calc_viewport_aoi(AoiPos),
    set_viewport_aoi(AoiPos, ViewportAoi),
    add_aoi_pos_maps(AoiPos),
    init_tower_aoi_grid_data2(T).

%% @doc 设置视野AoiPos 视野中的aoi坐标 [AoiPos|...]
set_viewport_aoi(AoiPos, ViewportAoi) ->
    put({viewport_aoi, AoiPos}, ViewportAoi).

%% @doc 获取视野AoiPos 视野中的aoi坐标 [AoiPos|...]
get_viewport_aoi(AoiPos) ->
    case get({viewport_aoi, AoiPos}) of
        undefined ->
            [];
        ViewportAoi ->
            ViewportAoi
    end.

%% @doc 增加视野AoiPosMaps
add_aoi_pos_maps(AoiPos) ->
    AoiPosMaps = get_aoi_pos_maps(),
    AoiPosMaps1 = maps:put(AoiPos, 1, AoiPosMaps),
    set_aoi_pos_maps(AoiPosMaps1).

%% @doc 设置视野AoiPosMaps #{AoiPos => 1}
set_aoi_pos_maps(AoiPosMaps) ->
    put(aoi_pos_maps, AoiPosMaps).

%% @doc 获取视野AoiPosMaps
get_aoi_pos_maps() ->
    case get(aoi_pos_maps) of
        undefined ->
            #{};
        AoiPosMaps ->
            AoiPosMaps
    end.

get_tower_data(TowerMaps, AoiPos) ->
    case maps:get(AoiPos, TowerMaps, undefined) of
        #tower_data{} = TowerData ->
            TowerData;
        _ ->
            AoiPosMaps = get_aoi_pos_maps(),
            case maps:is_key(AoiPos, AoiPosMaps) of
                true ->
                    init_tower_data(AoiPos);
                _ ->
                    undefined
            end
    end.

set_tower_data(TowerMaps, AoiPos, TowerData) ->
    InitTowerData = init_tower_data(AoiPos),
    case TowerData == InitTowerData of
        true ->
            maps:remove(AoiPos, TowerMaps);
        _ ->
            maps:put(AoiPos, TowerData, TowerMaps)
    end.

init_tower_data(AoiPos) ->
    #tower_data{aoi_pos = AoiPos}.

%% @doc 根据Uid获取object类型 - 默认为OBJ_AOI_TYPE_OBJECT
get_object_aoi_type_by_uid(#uid{type = ?UID_TYPE_PLAYER}) ->
    ?OBJ_AOI_TYPE_WATCHER;
get_object_aoi_type_by_uid(#uid{type = ?UID_TYPE_NPC}) ->
    ?OBJ_AOI_TYPE_WATCHER;
get_object_aoi_type_by_uid(_) ->
    ?OBJ_AOI_TYPE_OBJECT.

%% @doc 通知tower_aoi_brocast_svr进行广播给obj_svr
broadcast(UidList, Msg) ->
    tower_aoi_brocast_svr ! {broadcast, UidList, Msg}.

do_broadcast(UidList, Msg) ->
    [begin ?OBJ_SVR(UidValue) ! Msg end || #uid{value = UidValue} <- UidList].


%% ====================== privite =============================================


%% @doc 计算视野圈的aoi格子列表
calc_viewport_aoi({AoiX, AoiY} = _AoiPos) ->
    RangeX = lists:seq(-?AOI_VIEWPORT_SIZE + AoiX, ?AOI_VIEWPORT_SIZE + AoiX),
    RangeY = lists:seq(-?AOI_VIEWPORT_SIZE + AoiY, ?AOI_VIEWPORT_SIZE + AoiY),
    [{AccX, AccY} || AccX <- RangeX, AccY <- RangeY].



